package com.ww.exercise.coroutine.easy.q6

import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import java.text.SimpleDateFormat
import java.util.*
import kotlin.system.measureTimeMillis

/**
 * 核心并发控制实现
 * 1、Semaphore（信号量）
 * 创建了一个初始许可为3的信号量，这意味着同时只能有3个协程获得许可执行
 * 2、withPermit
 * Semaphore的扩展函数，作用是
 * 首先获取一个许可（如果没有可用许可则挂起等待）
 * 执行传入的代码块
 * 无论代码块正常执行还是抛出异常，都会自动释放许可
 */

// 模拟第三方文件上传接口
suspend fun uploadFile(field: Int): Boolean {
    val timeFormat = SimpleDateFormat("HH:mm:ss.SSS")
    val currentTime = timeFormat.format(Date())

    println("文件${field}开始上传 - $currentTime - 线程：${Thread.currentThread().name}")

    // 模拟上传耗时（1-2秒）
    delay((1000..2000).random().toLong())

    val finishTime = timeFormat.format(Date())
    println("文件${field}上传完成 - $finishTime - 线程：${Thread.currentThread().name}")

    return true
}

fun main() = runBlocking {
    val totalFiles = 100 // 总文件数
    val maxConcurrency = 3 // 最大并发数

    // 创建信号量，初始许可为maxConcurrency
    val semaphore = Semaphore(maxConcurrency)

    println("开始处理 $totalFiles 个文件上传，最大并发数限制为$maxConcurrency")

    // 测量总耗时
    val totalTime = measureTimeMillis {
        // 启动1000个文件上传任务
        val jobs = List(totalFiles) { fileId ->
            launch(Dispatchers.IO) {
                // 获取信号量许可，控制并发
                semaphore.withPermit {
                    uploadFile(fileId + 1) // 文件ID从1开始
                }
            }
        }

        // 等待所有任务完成
        jobs.joinAll()
    }
    println("所有文件上传完成，总耗时：${totalTime}ms")
}